package com.ddm.service.vxService;


import com.ddm.exception.LoginFailedException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;

/**
 * 微信接口服务类：封装微信小程序相关API调用
 */
@Service
@Slf4j
public class WechatApiService {

    // 微信配置（appid、secret等）
    @Value("${cx.open.appId}")
    private String appid;

    @Value("${cx.open.appSecret}")
    private String secret;

    @Autowired
    private ObjectMapper objectMapper; // JSON解析工具

    /**
     * 1. 获取微信接口调用凭证（access_token）
     * 文档：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html
     */

    public String getAccessToken() {
        // 构建请求URL
        String url = String.format(
                "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
                appid,
                secret
        );

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = httpClient.execute(httpGet);
            String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            log.info("获取access_token响应：{}", responseBody);

            // 解析响应（修复核心逻辑）
            JsonNode jsonNode = objectMapper.readTree(responseBody);
            // 1. 先判断 errcode 字段是否存在（失败响应才会有该字段）
            JsonNode errCodeNode = jsonNode.get("errcode");
            if (errCodeNode != null && errCodeNode.asInt(0) != 0) {
                // 2. 仅当 errcode 存在且非0时，才处理错误
                String errMsg = jsonNode.get("errmsg").asText("未知错误");
                log.error("获取access_token失败：{}({})", errMsg, errCodeNode.asInt());
                throw new LoginFailedException("获取微信接口凭证失败");
            }

            // 3. 成功响应：提取 access_token（需判断是否存在，避免后续空指针）
            JsonNode accessTokenNode = jsonNode.get("access_token");
            if (accessTokenNode == null || accessTokenNode.isNull() || accessTokenNode.asText().isEmpty()) {
                log.error("获取access_token失败：响应中未包含有效的 access_token");
                throw new LoginFailedException("获取微信接口凭证失败");
            }
            return accessTokenNode.asText();
        } catch (Exception e) {
            log.error("获取access_token异常", e);
            throw new LoginFailedException("获取微信接口凭证异常");
        }
    }

    /**
     * 2. 通过登录code获取用户openid（用户在当前小程序的唯一标识）
     * 文档：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
     */
    public String getOpenidByLoginCode(String loginCode) {
        // 构建请求URL
        String url = String.format(
                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                appid,
                secret,
                loginCode
        );

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = httpClient.execute(httpGet);
            String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            log.info("获取openid响应：{}", responseBody);

            // 解析响应
            JsonNode jsonNode = objectMapper.readTree(responseBody);
            JsonNode errCodeNode = jsonNode.get("errcode");
            if (errCodeNode != null && errCodeNode.asInt(0) != 0) {
                String errMsg = jsonNode.get("errmsg").asText("未知错误");
                log.error("获取openid失败：{}({})", errMsg, errCodeNode.asInt());
                throw new LoginFailedException("微信登录失败");
            }

            return jsonNode.get("openid").asText();
        } catch (Exception e) {
            log.error("获取openid异常", e);
            throw new LoginFailedException("微信登录异常");
        }
    }

    /**
     * 3. 通过手机号授权code获取用户手机号
     * 文档：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/phonenumber/phonenumber.getPhoneNumber.html
     */
    public String getPhoneNumberByCode(String phoneCode) {
        // 先获取access_token
        String accessToken = getAccessToken();

        // 构建请求URL和参数
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
        String jsonBody = String.format("{\"code\":\"%s\"}", phoneCode); // 请求体JSON

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8));

            CloseableHttpResponse response = httpClient.execute(httpPost);
            String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            log.info("获取手机号响应：{}", responseBody);

            // 解析响应
            JsonNode jsonNode = objectMapper.readTree(responseBody);
            int errCode = jsonNode.get("errcode").asInt(0);
            if (errCode != 0) {
                String errMsg = jsonNode.get("errmsg").asText("未知错误");
                log.error("获取手机号失败：{}({})", errMsg, errCode);
                throw new LoginFailedException("获取手机号失败");
            }

            // 提取手机号（注意实体类中字段为phoneNum）
            return jsonNode.path("phone_info").path("phoneNumber").asText();
        } catch (Exception e) {
            log.error("获取手机号异常", e);
            throw new LoginFailedException("获取手机号异常");
        }
    }
}
